﻿using Ducu.GLB.Global;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Global.Core.ExtensionMethod;
using Ducu.BLL.Entity.Component;

namespace Ducu.BLL.Entity
{
    public class Plan : BaseEntity
    {
        public virtual User Vower { get; set; }
        public virtual string Title { get; set; }
        public virtual string Description { get; set; }
        public virtual string FulfilWeekdays { get; set; }
        public virtual DateTime From { get; set; }
        public virtual DateTime? To { get; set; }
        public virtual Link Proof { get; set; }
        public virtual int Expire { get; set; }
        public virtual int DaysOfLeave { get; set; }
        public virtual int MaxNumberOfSupervisors { get; set; }
        public virtual IList<User> Supervisors { get; set; }
        public virtual IList<Keyword> KeyWords { get; set; }
        public virtual RedbagPolicy Policy { get; set; }

        public virtual bool StillNeedSupervisors()
        {
            return DateTime.Now < To
                && GetStillNeedSupervisorNumber() > 0;
        }

        public virtual void JoinedBy(User supervisor)
        {
            Supervisors = Supervisors ?? new List<User>();
            Supervisors.Add(supervisor);

            Message message = new Message
            {
                SendTo = Vower,
                Content = PlanJoinTemplate.MakeLink(
                    supervisor.Profile.DisplayName, supervisor.Id.ToString(), 
                    Title, Id.ToString()),
                Reply = ReplyTemplate.OnUser(supervisor.Id.ToString())
            };
            supervisor.AddMessage(message);
        }

        public virtual int GetStillNeedSupervisorNumber()
        {
            if (Supervisors == null)
            {
                return MaxNumberOfSupervisors;
            }
            return MaxNumberOfSupervisors - Supervisors.Count;
        }

        public virtual bool Rest(DateTime date)
        {
            IList<int> days = FulfilWeekdays.ToListIntDays();
            return !days.Contains(date.GetChineseWeekDay());
        }

        public virtual Status CanComplete(DateTime date, DateTime now)
        {
            //Note: always put Rest() check in the first
            if (Rest(date))
            {
                return Status.Rest;
            }

            if (now < date)
            {
                return Status.Future;
            }

            //because date is just the begining of one day: 00:00
            //and Expire = 0 means: complete until the day is over
            if (date.AddDays(1) > now.AddDays(-Expire))
            {
                return Status.WaitComplete;
            }
            else
            {
                return Status.NotComplte;
            }
        }

        public virtual Status CanComplete(DateTime date)
        {
            return CanComplete(date, DateTime.Now);
        }


        //TODO: I want it implement here very much, but seems it's hard work?
        //public virtual Status Check(Task task, DateTime now, DateTime checkDate)
        //{
        //    if (Rest(checkDate))
        //    {
        //        return Status.Rest;
        //    }
        //    else
        //    {
        //        if (task == null)
        //        {
        //            return CanComplete(task.CompleteDate, now);
        //        }
        //        else
        //        {
        //            return task.GetStatus();
        //        }
        //    }
        //}

        //public virtual Status Check(Task task)
        //{
        //    return Check(task, DateTime.Now);
        //}
    }

    public static class PlanExtension
    {
        public static string ToStringDays(this IList<int> source)
        {
            string strDays = string.Empty;
            foreach (var day in source)
            {
                strDays += day + ",";
            }
            return strDays;
        }

        public static IList<int> ToListIntDays(this string source)
        {
            IList<int> result = new List<int>();
            string[] days = source.Split(',');
            foreach (var item in days)
            {
                int day;
                if (int.TryParse(item, out day))
                {
                    result.Add(day);
                }
            }
            return result;
        }

        public static string ToStringKeywords(this IList<Keyword> source)
        {
            string result = string.Empty;
            foreach (var item in source)
            {
                result += (item.Content + " ");
            }
            return result;
        }
    }
}
